﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DeVerwachtingAmeland
{
    public partial class Form1 : Form
    {

        public const int WM_SETTEXT = 0x000C;
        public const int WM_GETTEXTLENGTH = 0x000E;
        public const int WM_GETTEXT = 0x000D; 
        /// <summary>
        /// Required designer variable.
        /// </summary>

        /// <summary>
        /// The FindWindow API
        /// </summary>
        /// <param name="lpClassName">the class name for the window to search for</param>
        /// <param name="lpWindowName">the name of the window to search for</param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
        /// The FindWindowEx API
        /// </summary>
        /// <param name="parentHandle">a handle to the parent window </param>
        /// <param name="childAfter">a handle to the child window to start search after</param>
        /// <param name="className">the class name for the window to search for</param>
        /// <param name="windowTitle">the name of the window to search for</param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle); 
        /// <summary>
        /// The GetWindow API
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="uCmd"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
        /// <summary>
        /// An enum that contains values for the GetWindowApi
        /// </summary>
        enum GetWindow_Cmd : uint
        {
            GW_HWNDFIRST = 0,
            GW_HWNDLAST = 1,
            GW_HWNDNEXT = 2,
            GW_HWNDPREV = 3,
            GW_OWNER = 4,
            GW_CHILD = 5,
            GW_ENABLEDPOPUP = 6
        }
        IntPtr hertzTextBoxHandle;//HertzTextbox handle from multitool
        IntPtr wattTextBoxHandle;//WattTextbox handle from multitool
        Bitmap[] MillPictures;//Bitmap that contains bacckground pictures of the mill
        Data_class getData; // An Data_class instance
        static Timer animationTime;//Timer for the loading speed of the mill animation
        static Timer refreshData;//Timer for getting Data
        int image = 0;//Current Mill image position
        PictureBox[] houses;//PictureBox array with all the houses
        int timerspeed;//this variable contains the time in nanoseconds
        public Form1()
        {
            //Use the Form1_KeyDown method when a key is pressed
            this.KeyDown += Form1_KeyDown;
            this.KeyPreview = true;
            this.hertzTextBoxHandle = getHertzHandle();
            this.wattTextBoxHandle = getWattHandle();
            getData = new Data_class(getHertzHandle(), getWattHandle());
            //fill the string array with the filenames
            initializeMillArray();
            InitializeComponent();
            MillImage.Size = new System.Drawing.Size(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
            MillImage.SendToBack();
            MillImage.Hide();
            NHLLogo.Hide();
            EndenLabel.Hide();
            EnergyLabel.Hide();
            TitleLabel.Hide();
            NHLLogo.Location = new System.Drawing.Point(SystemInformation.VirtualScreen.Width - 240, SystemInformation.VirtualScreen.Height - 170);
            TitleLabel.Location = new System.Drawing.Point(SystemInformation.VirtualScreen.Width - 1030, 20);
            NHLLogo.BackColor = Color.Transparent;
            NHLLogo.Parent = MillImage;
            TitleLabel.BackColor = Color.Transparent;
            TitleLabel.Parent = MillImage;
            EndenLabel.BackColor = Color.Transparent;
            EndenLabel.Parent = MillImage;
            EnergyLabel.BackColor = Color.Transparent;
            EnergyLabel.Parent = MillImage;
            createPictureboxes();

        }
        /// <summary>
        /// Method For the Start Button, this Method lets the Form go to fullscreen and then starts the whole Data process
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Start_Click(object sender, EventArgs e)
        {
            int hwnd = 0;
            double result;
            hwnd = FindWindow(null, "DVE MultiTool 1.2.0 - Build: Aug 14 2013");
            //if hwnd is not equal to 0, the application is running - continue
            //if getdata.getwattinfo returns a value that can be parsed to a double - continue
            if (hwnd != 0 && (double.TryParse(getData.getWattInfo(), out result)))
            {
                Start.Hide();
                changeScreen();
                start_animation();
                startShowingData();
                Logo.Hide();
            }
            //if hwnd is zero the application is not running- prompt user to start it
            else if (hwnd == 0)
            {
                DialogResult dialogResult = MessageBox.Show("MultiTool kon niet gevonden worden.\n\nStart MultiTool en probeer opnieuw.",
                "Niet gevonden!",
                MessageBoxButtons.OK,
                MessageBoxIcon.Hand,
                MessageBoxDefaultButton.Button1);
                Application.Exit();
            }
            // if hwnd is not zero then the application couldn't get data from multitool- give an error
            else if (hwnd != 0)
            {
                DialogResult dialogResult = MessageBox.Show("Data ophalen mislukt!\n\nZorg ervoor dat MultiTool verbonden is!",
                    "Fout!",
                    MessageBoxButtons.RetryCancel,
                    MessageBoxIcon.Error,
                    MessageBoxDefaultButton.Button1);
                //if user wants to retry to connect, restart the method
                if (dialogResult == DialogResult.Retry)
                {
                    Start_Click(sender, e);
                }
            }
        }
        /// <summary>
        /// This method gets the Api handles for the Watt textbox of MultiTool
        /// </summary>
        /// <returns></returns>
        IntPtr getWattHandle()
        {
            int hwnd = 0;
            hwnd = FindWindow(null, "DVE MultiTool 1.2.0 - Build: Aug 14 2013");

            IntPtr hwndChild = IntPtr.Zero;
            IntPtr hwndNeighbour = IntPtr.Zero;
            //Get a handle for the "Power Textbox"
            hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, null, "");
            if (hwndChild != null)
            {
                hwndChild = FindWindowEx((IntPtr)hwndChild, IntPtr.Zero, null, "Monitor");
                if (hwndChild != null)
                {
                    hwndChild = FindWindowEx((IntPtr)hwndChild, IntPtr.Zero, null, "Grid Feed In");
                    IntPtr buffer = hwndChild;
                    if (hwndChild != null)
                    {
                        hwndChild = FindWindowEx((IntPtr)hwndChild, IntPtr.Zero, null, "W");
                        hwndNeighbour = GetWindow(hwndChild, (int)GetWindow_Cmd.GW_HWNDNEXT);
                    }
                }
            }
            return hwndNeighbour;
        }
        /// <summary>
        /// This method gets the Api handles for the hertz textbox of MultiTool
        /// </summary>
        /// <returns></returns>
        IntPtr getHertzHandle()
        {
            int hwnd = 0;
            hwnd = FindWindow(null, "DVE MultiTool 1.2.0 - Build: Aug 14 2013");

            IntPtr hwndChild = IntPtr.Zero;
            IntPtr hwndNeighbour = IntPtr.Zero;
            //Get a handle for the "Power Textbox"
            hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, null, "");
            if (hwndChild != null)
            {
                hwndChild = FindWindowEx((IntPtr)hwndChild, IntPtr.Zero, null, "Monitor");
                if (hwndChild != null)
                {
                    hwndChild = FindWindowEx((IntPtr)hwndChild, IntPtr.Zero, null, "Inverter Input");
                    IntPtr buffer = hwndChild;
                    if (hwndChild != null)
                    {
                        hwndChild = FindWindowEx((IntPtr)hwndChild, IntPtr.Zero, null, "Frequency");
                        hwndNeighbour = GetWindow(hwndChild, (int)GetWindow_Cmd.GW_HWNDNEXT);
                    }
                }
            }
            return hwndNeighbour;
        }
        /// <summary>
        /// Sets screen to Fullscreen and back when the button is clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FullscreenButton_Click(object sender, EventArgs e)
        {
            changeScreen();
        }

        /// <summary>
        /// Method that responds to keypresses
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                Application.Exit();
                // prevent child controls from handling this event as well
                e.SuppressKeyPress = true;
                
            }
            //When F1 is pressed, display a help popup
            else if (e.KeyCode == Keys.F1 && !this.TopMost)
            {
                AboutBox1 box = new AboutBox1();
                box.ShowDialog();
            }
            //When F5 is pressed, start process
            else if (e.KeyCode == Keys.F5)
            {
                Start_Click(sender, e);
                e.SuppressKeyPress = true;
            }
            //else if (e.KeyCode == Keys.F10)
            //{
            //    getData.setInfo();
            //}
            
        }
        /// <summary>
        /// This Method Closes the aplication
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseButton_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        /// <summary>
        /// This method initializes the Mill Array
        /// </summary>
        void initializeMillArray()
        {
            MillPictures = new Bitmap[127];
            for (int i = 0; i < MillPictures.Length; i++)
            {
                MillPictures[i] = (Bitmap)DeVerwachtingAmeland.Properties.Resources.ResourceManager.GetObject("molen__" + (1 + i) + "_");
            }
        }
         ///<summary>
         ///Starts the animation timer for the windmill
         ///</summary>
        public void start_animation()
        {
            if (this.TopMost)
            {
                if (!(timerspeed==0))
                {
                    animationTime = new Timer(); // Set up the timer for 1 second
                    animationTime.Interval = timerspeed; // Time in milliseconds.
                    animationTime.Tick += AnimationTimer_Tick;
                    animationTime.Start();  
                }
                else
                {
                    animationTime = new Timer(); // Set up the timer for 1 second
                    animationTime.Interval = 5000; // Time in milliseconds.
                    animationTime.Tick += AnimationTimer_Tick;
                    animationTime.Start(); 
                }              
            }
            else
            {
                MillImage.Hide();
            }

        }
        /// <summary>
        /// As soon as the timer time has passed it changes the displayed image and restarts the timer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AnimationTimer_Tick(object sender, EventArgs e)
        {
            animationTime.Stop();
            changeImage();
            start_animation();
        }
        /// <summary>
        /// This Method changes the currently displayed Image
        /// </summary>
        void changeImage()
        {
            image++;
            if (image == 127)
            {
                image = 0;
            }
            MillImage.Image = MillPictures[image];
            //MillImage.Load(MillPictures[image]);
        }
        /// <summary>
        /// This method changes from  normal screen to fullscreen and vice versa. 
        /// </summary>
        void changeScreen()
        {
            if (this.TopMost)
            {
                this.FormBorderStyle = FormBorderStyle.Sizable;
                this.WindowState = FormWindowState.Normal;
                MillImage.Hide();
                CloseButton.Show();
                NHLLogo.Hide();
                EndenLabel.Hide();
                EnergyLabel.Hide();
                TitleLabel.Hide();
                Cursor.Show();
            }
            else
            {
                this.FormBorderStyle = FormBorderStyle.None;
                this.WindowState = FormWindowState.Maximized;
                MillImage.Show();
                CloseButton.Hide();
                NHLLogo.Show();
                EndenLabel.Show();
                EnergyLabel.Show();
                TitleLabel.Show();
                Cursor.Hide();
            }
            this.TopMost = !this.TopMost;
        }
        /// <summary>
        /// Creates the Pictures array filled with house images
        /// </summary>
        void createPictureboxes()
        {
            houses = new PictureBox[25];
            for (int i = 0; i < 24; i++)
            {
                houses[i] = new PictureBox();
                houses[i].BackColor = System.Drawing.Color.Transparent;
                houses[i].BackgroundImage = global::DeVerwachtingAmeland.Properties.Resources.House;
                houses[i].BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
                houses[i].InitialImage = null;
                if (i < 12)
                {
                    houses[i].Location = new System.Drawing.Point(10 + (50 * i), SystemInformation.VirtualScreen.Height - 225);
                }
                else
                {
                    houses[i].Location = new System.Drawing.Point(10 + (50 * (i-12)), SystemInformation.VirtualScreen.Height - 155);
                }
                
                houses[i].Name = "House";
                houses[i].Size = new System.Drawing.Size(50, 50);
                houses[i].SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
                houses[i].TabStop = false;
                Controls.Add(houses[i]);
                houses[i].Parent = MillImage;
                houses[i].Refresh();
            }
        }
        /// <summary>
        /// This Method starts the Data Process
        /// </summary>
        public void startShowingData()
        {
                refreshData = new Timer(); // Set up the timer for 1 second
                refreshData.Interval = 500; // Time in milliseconds.
                refreshData.Tick += Data_Tick;
                refreshData.Start();
        }
        /// <summary>
        /// This is Method is used in conjuction with  the above method
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Data_Tick(object sender, EventArgs e)
        {
            refreshData.Stop();
            dataDisplay();
            startShowingData();
        }
        /// <summary>
        /// This method Gets the current Data in the textboxes and then processes the information so it can be displayed on screen
        /// </summary>
        void dataDisplay()
        {            
            double hertz = Convert.ToDouble(getData.getHertzInfo());
            double enden = hertz * 8 / 3;
            if (enden == 0)
            {
                timerspeed = 10000;
            }
            else
	        {
            timerspeed = Convert.ToInt32((1000 /127)/((enden/240)));
	        }           
            if (timerspeed == 0)
            {
                timerspeed = 2500; 
            }
            EndenLabel.Text = String.Format("De molen draait nu {0:0} enden\nDit zijn {1:0.0} omwentelingen per minuut", enden, enden / 4);
            double watt = Convert.ToDouble(getData.getWattInfo());
            EnergyLabel.Text = String.Format("De molen levert nu {0:0} Watt\nDit is genoeg voor {1:0} huishoudens", watt, (int)(watt / 400));
            showHouses((int)(watt/400));
        }
        /// <summary>
        /// This method shows an X amount of houses on screen depending on the current Watt generation.
        /// </summary>
        /// <param name="x"></param>
        void showHouses(int x)
        {
            if (x > 24)
            {
                x = 24;
            }
            for (int i = 0; i < 24; i++)
            {
                houses[i].Hide();
            }
            for (int i = 0; i < x; i++)
            {
                houses[i].Show();
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            
        }
    }
}
